using System;
using System.Data;
using System.Text;
using System.Reflection;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;

using Suplex.Data;
using Suplex.Forms;
using Suplex.General;
using Suplex.Security;
using Suplex.Security.Standard;

using dbg = System.Diagnostics.Debug;

namespace Suplex.WebForms
{
	/// <summary>
	/// Provides secuirty, extended validation properties, and auto-validation.
	/// </summary>
	[ToolboxItem( true ),
       System.Drawing.ToolboxBitmap( typeof( System.Web.UI.WebControls.GridView ) )]
	[EventBindings( EventBindingsAttribute.BaseEvents.WebForms, ControlEvents.None )]
	public class sGridView : System.Web.UI.WebControls.GridView, IValidationControl, ISecureContainer, IWebExtra	//, IPostBackDataHandler
	{
		private string _uniqueName = null;
		private DataAccessLayer _dal = new DataAccessLayer();
		private SecurityAccessor _sa = null;
		private SecurityResultCollection _sr = null;
		private ValidationAccessor _va = null;

		private string _tag = null;
		private object _tagObject = null;


        #region custom gv vars
		private const string __this = "__this";
		private RecordRightsPermissionsCacheHandler _rrCache = null;

		private bool _hideDataKeyNameColumns = true;
		private bool _hideAutoGeneratedColumnDuplicates = true;
		private List<DataControlField> _displayColumns = null;
        private bool _showTitleRow = true;
		private bool _showFooterRow = true;
        private bool _allowFiltering = true;
        private string _titleText = string.Empty;
		private string _noListRightsText = string.Empty;
		private string _footerText = string.Empty;
		private TableCell _footerTextCell = null;
		private bool _showHeaderNewItem = true;
        private string _titleNewItemText = string.Empty;
        private string _titleNewItemImageURL = string.Empty;
        private string _titleRowCssClass = string.Empty;
        private string _filterRowCssClass = string.Empty;
		private string _footerRowCssClass = string.Empty;
		private string _autogeneratedColumnCssClass = string.Empty;
		private string _emptyDataFooterRowCssClass = string.Empty;
		private ITemplate _titleTemplate = null;
		private ITemplate _footerTemplate = null;
		private ITemplate _emptyDataTitleTemplate = null;
		private ITemplate _emptyDataFooterTemplate = null;
		private const string _newItemCommandName = "New";
        private const string _filterCommandName = "Filter";
		private string _filterItemText = string.Empty;
		private string _filterItemImageURL = string.Empty;
		private GridViewRow _filterRow = null;
		//private DataView _filterData = null;
		private bool _showFilterExpressionText = true;
		private string _filterExpressionText = string.Empty;
		private string _filterExpressionRowCssClass = string.Empty;
		private ITemplate _filterExpressionTemplate = null;
		private ImageButton _new = null;
		private ImageButton _fil = null;
		private string _selectImageUrl = string.Empty;
		private string _insertImageUrl = string.Empty;
		private string _editImageUrl = string.Empty;
		private string _updateImageUrl = string.Empty;
		private string _deleteImageUrl = string.Empty;
		private string _cancelImageUrl = string.Empty;
		//private StringDictionary _filterFieldData = new StringDictionary();
		private List<string> _dataFieldNames = new List<string>();
		private bool _dataFieldNamesCollected = false;
		#endregion


        #region Events
        public event System.EventHandler NewItemClick;
        public event sGridViewFilterEventHandler FilterClick;
        protected void OnNewItemClick(object sender, EventArgs e)
        {
            if( NewItemClick != null )
            {
                NewItemClick( sender, e );
            }
        }
        protected void OnFilterClick(object sender, sGridViewFilterEventArgs e)
        {
            if( FilterClick != null )
            {
                FilterClick( sender, e );
            }
        }

		public event sGridViewFilterColumnEventHandler FilterColumnCreated;
		protected void OnFilterColumnCreated(object sender, sGridViewFilterColumnEventArgs e)
		{
			if( FilterColumnCreated != null )
			{
				FilterColumnCreated( sender, e );
			}
		}
		#endregion


        #region ctor/validation/security impl
        public sGridView() : base()
        {
			_sa = new sGridViewSecurityAccessor( this, new AceType[2] { AceType.UI, AceType.Record } );
			_sr = _sa.Descriptor.SecurityResults;
			_va = new ValidationAccessor( this, TypeCode.Empty );

			//this.CacheRecordRights();
			_rrCache = new RecordRightsPermissionsCacheHandler( this.ViewState );
			_rrCache.CacheResults( __this, _sr );

			_new = new ImageButton();
			_new.ID = "NewItemImg";
			//_new.Command += new CommandEventHandler( NewItemOrFilter_Command );	//04/30/2006
			_fil = new ImageButton();
			_fil.ID = "FilterImg";
			//_fil.Command += new CommandEventHandler( NewItemOrFilter_Command );	//04/30/2006
		}

		protected override void OnInit(EventArgs e)
		{
			_sa.EnsureDefaultState();

			base.OnInit( e );
		}

		protected override void OnPreRender(EventArgs e)
		{
			this.ApplySecurity();

			base.OnPreRender( e );
		}

		protected override object SaveViewState()
		{
			object baseState = base.SaveViewState();

			object[] s = new object[6];

			s[0] = baseState;
			s[1] = _tag;
			s[2] = _filterExpressionText;
			s[3] = _titleText;
			s[4] = _showHeaderNewItem;
			s[5] = _filterItemText;

			return s;
		}

		/// <summary>
		/// Load State from the array of objects that was saved at SavedViewState.
		/// </summary>
		/// <param name="savedState">State information to load.</param>
		protected override void LoadViewState(object savedState)
		{
			object[] s = (object[])savedState;

			if( s[0] != null )
				base.LoadViewState( s[0] );

			if( s[1] != null )
				_tag = (string)s[1];

			if( s[2] != null )
				_filterExpressionText = (string)s[2];

			if( s[3] != null )
				_titleText = (string)s[3];

			if( s[4] != null )
				_showHeaderNewItem = (bool)s[4];

			if( s[5] != null )
				_filterItemText = (string)s[5];
		}


		[ParenthesizePropertyName( true ), Category( "Suplex" )]
		public string UniqueName
		{
			get
			{
				return string.IsNullOrEmpty( _uniqueName ) ? base.UniqueID : _uniqueName;
			}
			set
			{
				_uniqueName = value;
			}
		}

		[Browsable( false ), Category( "Suplex" )]
		public Suplex.Data.DataAccessLayer DataAccessLayer
		{
			get { return _dal; }
			set { _dal = value; }
		}


		#region Validation Implementation
		[TypeConverter( typeof( ExpandableObjectConverter ) ), Category( "Suplex" ),
		DesignerSerializationVisibility( DesignerSerializationVisibility.Content ),
		Description( "Provides access to Validation management properties and tools." )]
		public IValidationAccessor Validation
		{
			get { return _va; }
		}

		public ValidationResult ProcessValidate(bool processFillMaps)
		{
			ValidationResult vr = null;
			if( this.Enabled )
			{
				vr = _va.ProcessEvent( null, ControlEvents.Validating, processFillMaps );
			}
			return vr;
		}

		private void OnEnabledChanged()
		{
			if( _sr[AceType.UI, UIRight.Enabled].AccessAllowed )
			{
				_va.ProcessEvent( null, ControlEvents.EnabledChanged, true );
			}
		}

		private void OnVisibleChanged()
		{
			if( _sr[AceType.UI, UIRight.Visible].AccessAllowed )
			{
				_va.ProcessEvent( null, ControlEvents.VisibleChanged, true );
			}
		}
		#endregion


		#region Security Implementation
		[TypeConverter( typeof( ExpandableObjectConverter ) ), Category( "Suplex" ),
		DesignerSerializationVisibility( DesignerSerializationVisibility.Content ),
		Description( "Provides access to Security management properties and tools." )]
		public SecurityAccessor Security
		{
			get { return _sa; }
		}

		public ICollection GetChildren()
		{
			return (ICollection)this.Controls;
		}

		public void ApplySecurity()
		{
			if( !this.DesignMode )
			{
				if( !_sr[AceType.UI, UIRight.Enabled].AccessAllowed )
				{
					base.Enabled = false;
				}
				if( !_sr[AceType.UI, UIRight.Visible].AccessAllowed )
				{
					base.Visible = false;
				}
			}

			_rrCache.CacheResults( __this, _sr );
		}

		[DefaultValue( false )]
		public override bool Visible
		{
			get
			{
				return base.Visible;
			}
			set
			{
				if( _sr[AceType.UI, UIRight.Visible].AccessAllowed )
				{
					if( base.Visible != value )
					{
						base.Visible = value;
						OnVisibleChanged();		//TODO: was commented, should be?
					}
				}
			}
		}

		[DefaultValue( false )]
		public override bool Enabled
		{
			get
			{
				return base.Enabled;
			}
			set
			{
				if( _sr[AceType.UI, UIRight.Enabled].AccessAllowed )
				{
					if( base.Enabled != value )
					{
						base.Enabled = value;
						OnEnabledChanged();		//TODO: was commented, should be?
					}
				}
			}
		}

		internal RecordRightsPermissionsCacheHandler RecordRightsCache
		{
			get { return _rrCache; }
		}


		//original proprietary implementation, left for reference puprposes
		//public virtual void ApplySecurity(AceType AceType, ArrayList DaclParameters, ArrayList SaclParameters)
		//{
		//    switch( AceType )
		//    {
		//        case AceType.UI:
		//        case AceType.Record:
		//        case AceType.Native:
		//        {
		//            this.SecurityDescriptor.EvalSecurity( AceType.UI, DaclParameters, SaclParameters );
		//            this.SecurityDescriptor.EvalSecurity( AceType.Record, DaclParameters, SaclParameters );
		//            //this.CacheRecordRights();
		//            _rrCache.CacheResults( __this, _sr );
		//            this.AuditAccess();
		//            SecurityBuilder.PropagateSecurity( this );
		//            break;
		//        }
		//    }
		//}



		private SortedList<string, SecurityDescriptor> _alternateSecurityDescriptors = new SortedList<string, SecurityDescriptor>();
		public SortedList<string, SecurityDescriptor> AlternateSecurityDescriptors
		{
			get { return _alternateSecurityDescriptors; }
			set { _alternateSecurityDescriptors = value; }
		}

		[Obsolete( "Use RecordRightsPermissionsCacheHandler.", true )]
		private void CacheRecordRights()
		{
			//ViewState[_rrList] = this.SecurityDescriptor.SecurityResults[AceType.Record, RecordRight.List].AccessAllowed;
			//ViewState[_rrSelect] = this.SecurityDescriptor.SecurityResults[AceType.Record, RecordRight.Select].AccessAllowed;
			//ViewState[_rrInsert] = this.SecurityDescriptor.SecurityResults[AceType.Record, RecordRight.Insert].AccessAllowed;
			//ViewState[_rrUpdate] = this.SecurityDescriptor.SecurityResults[AceType.Record, RecordRight.Update].AccessAllowed;
			//ViewState[_rrDelete] = this.SecurityDescriptor.SecurityResults[AceType.Record, RecordRight.Delete].AccessAllowed;
		}
        #endregion
        #endregion


        #region GridView Overrides/Custom Props
		#region props
		public bool HideDataKeyNameColumns
        {
            get { return _hideDataKeyNameColumns; }
            set { _hideDataKeyNameColumns = value; }
        }

		public bool HideAutoGeneratedColumnDuplicates
		{
			get { return _hideAutoGeneratedColumnDuplicates; }
			set { _hideAutoGeneratedColumnDuplicates = value; }
		}

		/// <summary>
		/// Returns the list of columns that are rendered for display.
		/// </summary>
		public List<DataControlField> DisplayColumns
        {
			get { return _displayColumns; }
        }

        public bool ShowTitleRow
        {
            get { return _showTitleRow; }
            set { _showTitleRow = value; }
        }

        public bool AllowFiltering
        {
            get { return _allowFiltering; }
            set { _allowFiltering = value; }
        }

        public string TitleText
        {
            get { return _titleText; }
            set { _titleText = value; }
        }

        public bool ShowTitleNewItem
        {
            get { return _showHeaderNewItem; }
            set { _showHeaderNewItem = value; }
        }

        public string TitleNewItemText
        {
            get { return _titleNewItemText; }
            set { _titleNewItemText = value; }
        }

        public string TitleNewItemImageURL
        {
            get { return _titleNewItemImageURL; }
            set { _titleNewItemImageURL = value; }
        }

        public string TitleRowCssClass
        {
            get { return _titleRowCssClass; }
            set { _titleRowCssClass = value; }
        }

		public string FilterItemText
		{
			get { return _filterItemText; }
			set { _filterItemText = value; }
		}

		public string FilterItemImageURL
		{
			get { return _filterItemImageURL; }
			set { _filterItemImageURL = value; }
		}

		public string FilterRowCssClass
        {
            get { return _filterRowCssClass; }
            set { _filterRowCssClass = value; }
        }

		public string FilterExpressionText
		{
			get { return _filterExpressionText; }
			set { _filterExpressionText = value; }
		}

		public string FilterExpressionRowCssClass
		{
			get { return _filterExpressionRowCssClass; }
			set { _filterExpressionRowCssClass = value; }
		}

		public string AutoGeneratedColumnCssClass
		{
			get { return _autogeneratedColumnCssClass; }
			set { _autogeneratedColumnCssClass = value; }
		}

		public bool ShowFilterExpressionText
		{
			get { return _showFilterExpressionText; }
			set { _showFilterExpressionText = value; }
		}

		public string NoListRightsText
		{
			get { return _noListRightsText; }
			set { _noListRightsText = value; }
		}

		public bool ShowFooterRow
		{
			get { return _showFooterRow; }
			set { _showFooterRow = value; }
		}

		public string FooterText
		{
			get { return _footerText; }
			set { _footerText = value; }
		}

		public string FormattedFooterText
		{
			get
			{
				if( this.AllowPaging && this.TotalRowCount > 0 )
				{
					//return string.Format( "Page {0} of {1} in {2} Total Rows", this.PageIndex + 1, this.PageCount, this.TotalRowCount );
					int f = this.PageIndex * this.PageSize;
					int t = f + this.PageSize;
					return string.Format( "Results {0} - {1} of {2} Total",
						f + 1,
						t > this.TotalRowCount ? this.TotalRowCount : t,
						this.TotalRowCount );
				}
				else
				{
					return string.Format( "{0} Total Records", this.TotalRowCount );
				}
			}
		}

		public string FooterRowCssClass
        {
            get { return _footerRowCssClass; }
			set { _footerRowCssClass = value; }
        }

		public string EmptyDataFooterRowCssClass
        {
			get { return _emptyDataFooterRowCssClass; }
			set { _emptyDataFooterRowCssClass = value; }
        }

		public int TotalRowCount
		{
			get { return this.ViewState["__totalRows"] == null ? -1 : (int)this.ViewState["__totalRows"]; }
			set { this.ViewState["__totalRows"] = value; }
		}

		public ITemplate TitleTemplate
        {
            get { return _titleTemplate; }
            set { _titleTemplate = value; }
		}

		public ITemplate FooterTemplate
		{
			get { return _footerTemplate; }
			set { _footerTemplate = value; }
		}

		public ITemplate EmptyDataTitleTemplate
		{
			get { return _emptyDataTitleTemplate; }
			set { _emptyDataTitleTemplate = value; }
		}

		public ITemplate EmptyDataFooterTemplate
		{
			get { return _emptyDataFooterTemplate; }
			set { _emptyDataFooterTemplate = value; }
		}

		[TemplateContainer( typeof( sFilterExpressionContainer ) )]
		public ITemplate FilterExpressionTemplate
		{
			get { return _filterExpressionTemplate; }
			set { _filterExpressionTemplate = value; }
		}

		public string SelectImageUrl { get { return _selectImageUrl; } set { _selectImageUrl = value; } }
		public string InsertImageUrl { get { return _insertImageUrl; } set { _insertImageUrl = value; } }
		public string EditImageUrl { get { return _editImageUrl; } set { _editImageUrl = value; } }
		public string DeleteImageUrl { get { return _deleteImageUrl; } set { _deleteImageUrl = value; } }
		#endregion


		public override object DataSource
		{
			get
			{
				return base.DataSource;
			}
			set
			{
				if( _rrCache[__this].List )
				{
					base.DataSource = value;
				}
				else
				{
					base.DataSource = new DataTable();
					this.EmptyDataText = !string.IsNullOrEmpty( _noListRightsText ) ? _noListRightsText : "You do not have rights to list records!";
				}
				this.GetTotalRows( value );
			}
		}
		private void GetTotalRows(object data)
		{
			if( data is DataSet )
			{
				this.TotalRowCount = ( (DataSet)data ).Tables[0].Rows.Count;
			}
			else if( data is DataTable )
			{
				this.TotalRowCount = ( (DataTable)data ).Rows.Count;
			}
			else if( data is DataView )
			{
				this.TotalRowCount = ( (DataView)data ).Count;
			}
			else if( data is System.Data.Common.DbDataReader )
			{
				this.TotalRowCount = ( (System.Data.Common.DbDataReader)data ).RecordsAffected;
			}
			else if( data is System.Collections.ICollection )
			{
				this.TotalRowCount = ( (System.Collections.ICollection)data ).Count;
			}
			//else if( data is System.Collections.Generic.ICollection<> )	//um, dunno how to do this yet
			//{
			//    this.TotalRowCount = ( (System.Collections.ICollection)data ).Count;
			//}
		}
		public override int PageIndex
		{
			get
			{
				return base.PageIndex;
			}
			set
			{
				base.PageIndex = value;
				if( _footerTextCell != null )
				{
					_footerTextCell.Text = this.GetFooterText();
				}
			}
		}

		/// <summary>
        /// Overriden to exclude DataKeyName fields from the Columns collection
        /// </summary>
        protected override AutoGeneratedField CreateAutoGeneratedColumn(AutoGeneratedFieldProperties fieldProperties)
        {
			if( !_dataFieldNamesCollected )
			{
				this.BuildDisplayNamesList();
			}


            bool exclude = false;

			if( _hideDataKeyNameColumns || _hideAutoGeneratedColumnDuplicates )
            {
				exclude = _dataFieldNames.Contains( fieldProperties.DataField.ToLower() );

				if( !exclude )
				{
					if( this.DataKeyNames.Length == 1 )
					{
						if( fieldProperties.DataField.ToLower() == this.DataKeyNames[0].ToLower() )
						{
							exclude = true;
						}
					}
					else
					{
						for( int i = 0; i < this.DataKeyNames.Length; i++ )
						{
							if( fieldProperties.DataField.ToLower() == this.DataKeyNames[i].ToLower() )
							{
								exclude = true;
								break;
							}
						}
					}
				}
            }

            if( exclude )
            {
				//dbg.WriteLine( "Excluded: " + fieldProperties.DataField );
                return null;
            }
            else
            {
				//dbg.WriteLine( "Included: " + fieldProperties.DataField );
                return base.CreateAutoGeneratedColumn( fieldProperties );
            }
        }

		protected override ICollection CreateColumns(PagedDataSource dataSource, bool useDataSource)
		{
			//SetFilterDataSource( dataSource );

			//initialize the array.  stores all the columns.
			_displayColumns = new List<DataControlField>();

			//Let the control create its normal column set.  autogenerated colums are _not_
			//strored in the base.Columns collection.
			ICollection baseColumns = base.CreateColumns( dataSource, useDataSource );

			//create some storage for separating the column types
			List<ISDataControlField> indexIsSpecified = new List<ISDataControlField>();
			List<ISDataControlField> indexNegOne = new List<ISDataControlField>();

			//grab all the ImDataControlFields and stuff em in strongly-typed list,
			//everything else goes into returnColumns array.
			IEnumerator c = baseColumns.GetEnumerator();
			while( c.MoveNext() )
			{
				if( string.IsNullOrEmpty( ( (DataControlField)c.Current ).ItemStyle.CssClass ) )
				{
					( (DataControlField)c.Current ).ItemStyle.CssClass = _autogeneratedColumnCssClass;
				}

				//CommandFields contain the links for record actions, so check perms
				if( c.Current is CommandField )
				{
					CheckPermissions( (CommandField)c.Current, useDataSource );

					CommandField f = (CommandField)c.Current;
					if( !f.ShowSelectButton && !f.ShowEditButton && !f.ShowInsertButton && !f.ShowDeleteButton )
					{
						f.Visible = false;
					}
				}
				if( c.Current is sCommandTemplateField )
				{
					CheckPermissions( (sCommandTemplateField)c.Current, useDataSource );

					sCommandTemplateField f = (sCommandTemplateField)c.Current;
					if( !f.ShowSelectButton && !f.ShowInsertButton && !f.ShowEditButton &&
						!f.ShowUpdateButton && !f.ShowDeleteButton && !f.ShowCancelButton )
					{
						f.Visible = false;
					}
				}


				if( c.Current is ISDataControlField )
				{
					switch( ( (ISDataControlField)c.Current ).DisplayIndex )
					{
						//index == Int32.MinValue ==> index not specified, use natural order
						case Int32.MinValue:
						{
							_displayColumns.Add( c.Current as DataControlField );
							break;
						}
						//index == -1 (or less than 0, but != sunglasses) ==> put last in list
						case -1:
						{
							indexNegOne.Add( c.Current as ISDataControlField );
							break;
						}
						//index >=0 ==> use hard index
						default:
						{
							indexIsSpecified.Add( c.Current as ISDataControlField );
							break;
						}
					}
				}
				else
				{
					//DataControlField not ISDataControlField, use natural order
					_displayColumns.Add( c.Current as DataControlField );
				}
			}

			foreach( ISDataControlField f in indexNegOne )
			{
				_displayColumns.Add( f as DataControlField );
			}

			foreach( ISDataControlField f in indexIsSpecified )
			{
				if( f.DisplayIndex < 0 || f.DisplayIndex > _displayColumns.Count )
				{
					_displayColumns.Insert( _displayColumns.Count, f as DataControlField );
				}
				else
				{
					_displayColumns.Insert( f.DisplayIndex, f as DataControlField );
				}
			}

			////iterate the ImDataControlFields list and re-order the columns
			//for( int m = 0; m < mCols.Count; m++ )
			//{
			//    //if index<0 (is -1), then add column onto end of collection
			//    if( mCols[m].DisplayIndex < 0 )
			//    {
			//    }   //else, insert it into requested index
			//    else //( mCols[m].DisplayIndex >= 0 )
			//    {
			//    }
			//}

			//we're done, return the ordered columns
			//dbg.WriteLine( string.Format( "CreateColumns:\t{0}\t{1}\t{2}", useDataSource, this.SecurityDescriptor.SecurityResults[AceType.Record, RecordRight.Select].AccessAllowed, System.DateTime.Now.ToLongTimeString() ) );
			////dbg.WriteLine( string.Format( "<GV> CreateColumns:\t{0}\t{1}\t{2}", useDataSource, (bool)ViewState[_rrList], System.DateTime.Now.ToLongTimeString() ) );
			dbg.WriteLine( string.Format( "<GV> CreateColumns:\t{0}\t{1}\t{2}", useDataSource, _rrCache[__this].List, System.DateTime.Now.ToLongTimeString() ) );
			return _displayColumns;
		}

		private void BuildDisplayNamesList()
		{
			_dataFieldNamesCollected = true;

			//foreach( DataControlField field in _displayColumns )
			foreach( DataControlField field in base.Columns )
			{
				if( field is BoundField )
				{
					_dataFieldNames.Add( ( (BoundField)field ).DataField.ToLower() );
				}
				else if( field is CheckBoxField )
				{
					_dataFieldNames.Add( ( (CheckBoxField)field ).DataField.ToLower() );
				}
				else if( field is HyperLinkField )
				{
					_dataFieldNames.Add( ( (HyperLinkField)field ).DataTextField.ToLower() );
					foreach( string urlField in ( (HyperLinkField)field ).DataNavigateUrlFields )
					{
						_dataFieldNames.Add( urlField.ToLower() );
					}
				}
				else if( field is ImageField )
				{
					_dataFieldNames.Add( ( (ImageField)field ).DataAlternateTextField.ToLower() );
					_dataFieldNames.Add( ( (ImageField)field ).DataImageUrlField.ToLower() );
				}

			}

		}

        private void CheckPermissions(CommandField field, bool useDataSource)
        {
            if( useDataSource )
            {
                field.ShowSelectButton = field.ShowSelectButton && _sr[AceType.Record, RecordRight.Select].AccessAllowed;
				field.ShowInsertButton = field.ShowInsertButton && _sr[AceType.Record, RecordRight.Insert].AccessAllowed;
				field.ShowEditButton = field.ShowEditButton && _sr[AceType.Record, RecordRight.Update].AccessAllowed;
				field.ShowDeleteButton = field.ShowDeleteButton && _sr[AceType.Record, RecordRight.Delete].AccessAllowed;
            }
            else
            {
				RecordRightsPermissionsSet r = _rrCache[__this];
				field.ShowSelectButton = field.ShowSelectButton && r.Select;
				field.ShowInsertButton = field.ShowInsertButton && r.Insert;
				field.ShowEditButton = field.ShowEditButton && r.Update;
				field.ShowDeleteButton = field.ShowDeleteButton && r.Delete;
            }
		}

		private void CheckPermissions(sCommandTemplateField field, bool useDataSource)
		{
			if( !string.IsNullOrEmpty( field.AlternateSecurityDescriptorKey )
				&& _alternateSecurityDescriptors.ContainsKey( field.AlternateSecurityDescriptorKey )
				&& _alternateSecurityDescriptors[field.AlternateSecurityDescriptorKey] != null )
			{
				if( useDataSource )
				{
					SecurityDescriptor sd = _alternateSecurityDescriptors[field.AlternateSecurityDescriptorKey];
					_rrCache.CacheResults( field.AlternateSecurityDescriptorKey, sd.SecurityResults );
				}

				RecordRightsPermissionsSet r = _rrCache[field.AlternateSecurityDescriptorKey];
				field.ShowSelectButton = field.ShowSelectButton && r.Select;
				field.ShowInsertButton = field.ShowInsertButton && r.Insert;
				field.ShowEditButton = field.ShowEditButton && r.Update;
				field.ShowUpdateButton = field.ShowUpdateButton && r.Update;
				field.ShowDeleteButton = field.ShowDeleteButton && r.Delete;
			}
			else if( useDataSource )
			{
				field.ShowSelectButton = field.ShowSelectButton && _sr[AceType.Record, RecordRight.Select].AccessAllowed;
				field.ShowInsertButton = field.ShowInsertButton && _sr[AceType.Record, RecordRight.Insert].AccessAllowed;
				field.ShowEditButton = field.ShowEditButton && _sr[AceType.Record, RecordRight.Update].AccessAllowed;
				field.ShowUpdateButton = field.ShowUpdateButton && _sr[AceType.Record, RecordRight.Update].AccessAllowed;
				field.ShowDeleteButton = field.ShowDeleteButton && _sr[AceType.Record, RecordRight.Delete].AccessAllowed;
			}
			else
			{
				RecordRightsPermissionsSet r = _rrCache[ __this ];
				field.ShowSelectButton = field.ShowSelectButton && r.Select;
				field.ShowInsertButton = field.ShowInsertButton && r.Insert;
				field.ShowEditButton = field.ShowEditButton && r.Update;
				field.ShowUpdateButton = field.ShowUpdateButton && r.Update;
				field.ShowDeleteButton = field.ShowDeleteButton && r.Delete;
			}

			if( string.IsNullOrEmpty( field.SelectImageUrl ) )
			{
				field.SelectImageUrl = _selectImageUrl;
			}
			if( string.IsNullOrEmpty( field.InsertImageUrl ) )
			{
				field.InsertImageUrl = _insertImageUrl;
			}
			if( string.IsNullOrEmpty( field.EditImageUrl ) )
			{
				field.EditImageUrl = _editImageUrl;
			}
			if( string.IsNullOrEmpty( field.UpdateImageUrl ) )
			{
				field.UpdateImageUrl = _updateImageUrl;
			}
			if( string.IsNullOrEmpty( field.DeleteImageUrl ) )
			{
				field.DeleteImageUrl = _deleteImageUrl;
			}
			if( string.IsNullOrEmpty( field.CancelImageUrl ) )
			{
				field.CancelImageUrl = _cancelImageUrl;
			}
		}

		protected override GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState)
        {
			if( _rrCache[__this].List )	//(bool)ViewState[_rrList]
			{
				//dbg.WriteLine( string.Format( "CreateRow: {0}\t{1}\t{2}\t{3}", rowIndex, dataSourceIndex, rowType, rowState ) );
				GridViewRow row = base.CreateRow( rowIndex, dataSourceIndex, rowType, rowState );

				Table grid = (Table)base.Controls[0];
				int cellCount = _displayColumns != null ? _displayColumns.Count : 1;	// 1;		//09062006

				//if adding the footer then we're done, so go ahead and create header and filter rows.
				bool isEmptyData = rowType == DataControlRowType.EmptyDataRow;
				if( rowType == DataControlRowType.Footer || isEmptyData )
				{
					if( grid.Rows.Count > 0 )
					{
						cellCount = grid.Rows[1].Cells.Count > _displayColumns.Count ? grid.Rows[1].Cells.Count : _displayColumns.Count;
					}

					//if( _showFilterExpressionText && _filterExpressionText != string.Empty ) grid.Rows.AddAt( 0, AddFilterExpressionRow( cellCount ) );
					if( _allowFiltering )
					{
						GridViewRow headerRow = null;
						TableRow filterRow = AddFilterRow( isEmptyData, out headerRow );
						if( isEmptyData )
						{
							grid.Rows.AddAt( 0, headerRow );
						}
						grid.Rows.AddAt( 0, filterRow );
					}
					if( _showTitleRow ) grid.Rows.AddAt( 0, AddTitleRow( cellCount, isEmptyData ) );

					if( _showFooterRow )
					{
						GridViewRow footer = AddFooterRow( cellCount, isEmptyData );
						if( footer != null )
						{
							grid.Rows.Add( footer );
						}
					}
				}

				return row;
			}
			else
			{
				this.EmptyDataText = !string.IsNullOrEmpty( _noListRightsText ) ? _noListRightsText : "You do not have rights to list records.";
				GridViewRow noRights = new GridViewRow( -1, -1, DataControlRowType.EmptyDataRow, DataControlRowState.Normal );
				noRights.CssClass = this.EmptyDataRowStyle.CssClass;
				return noRights;
			}
        }

		protected override void InitializePager(GridViewRow row, int columnSpan, PagedDataSource pagedDataSource)
		{
			base.InitializePager( row, columnSpan - 1, pagedDataSource );

			Table ftrContent = new Table();
			ftrContent.BorderWidth = Unit.Pixel( 0 );
			ftrContent.CellPadding = 0;
			ftrContent.CellSpacing = 0;
			ftrContent.Width = new Unit( 100, UnitType.Percentage );
			ftrContent.CssClass = _footerRowCssClass;

			TableRow ftrRow = new TableRow();
			ftrRow.CssClass = _footerRowCssClass;
			ftrContent.Rows.Add( ftrRow );

			TableCell p = row.Cells[0];
			row.Cells.RemoveAt( 0 );
			ftrRow.Cells.Add( p );

			TableCell c = new TableCell();
			c.HorizontalAlign = HorizontalAlign.Right;
			c.Text = this.GetFooterText();
			ftrRow.Cells.Add( c );

			row.Cells.Add( new TableCell() );
			row.Cells[0].ColumnSpan = columnSpan;
			row.Cells[0].Controls.Add( ftrContent );
		}

		private TableRow AddTitleRow(int cellCount, bool isEmptyData)
        {
			ITemplate tt = !isEmptyData ? _titleTemplate : _emptyDataTitleTemplate;

            GridViewRow titleRow = new GridViewRow( -1, -1, DataControlRowType.Header, DataControlRowState.Normal );
			titleRow.CssClass = _titleRowCssClass;
            TableCell titlebar = new TableCell();
			titlebar.ColumnSpan = cellCount;
            titleRow.Cells.Add( titlebar );

			if( tt == null )
            {
                Table hdrContent = new Table();
				hdrContent.BorderWidth = Unit.Pixel( 0 );
				hdrContent.CellPadding = 0;
				hdrContent.CellSpacing = 0;
				hdrContent.CssClass = _titleRowCssClass;
                TableRow hdrRow = new TableRow();
				hdrRow.CssClass = _titleRowCssClass;
                hdrContent.Rows.Add( hdrRow );

                TableCell hdrTitle = new TableCell();
				hdrTitle.CssClass = _titleRowCssClass;
                hdrTitle.Text = _titleText;
                hdrRow.Cells.Add( hdrTitle );


				if( _allowFiltering || ( _showHeaderNewItem && _rrCache[__this].Insert ) )	//(bool)ViewState[_rrInsert]
				{
					TableCell hdrNew = new TableCell();
					hdrNew.HorizontalAlign = HorizontalAlign.Right;
					hdrNew.Wrap = false;
					hdrRow.Cells.Add( hdrNew );

					if( _allowFiltering )
					{
						LinkButton filter = new LinkButton();
						filter.ID = "FilterLnk";
						filter.Text = !string.IsNullOrEmpty( _filterItemText ) ? _filterItemText : "Filter";
						filter.Text = RenderUtil.RenderAccessKey( filter.Text, filter );
						filter.CommandName = _filterCommandName;
						//filter.Command += new CommandEventHandler( NewItemOrFilter_Command );	//04/30/2006
						hdrNew.Controls.Add( filter );

						if( _filterItemImageURL != null && _filterItemImageURL != string.Empty )
						{
							//ImageButton filterImage = new ImageButton();
							//_fil = filterImage;
							//_fil.ID = "FilterImg";
							//_fil.Command += new CommandEventHandler( NewItemOrFilter_Command );
							_fil.ImageUrl = _filterItemImageURL;
							_fil.CommandName = _filterCommandName;
							hdrNew.Controls.Add( new LiteralControl( "&nbsp;" ) );
							hdrNew.Controls.Add( _fil );
						}
					}

					if( _showHeaderNewItem && _rrCache[__this].Insert )	//(bool)ViewState[_rrInsert]
					{
						if( _allowFiltering )
						{
							hdrNew.Controls.Add( new LiteralControl( "&nbsp;|&nbsp;" ) );
						}

						LinkButton newLink = new LinkButton();
						newLink.ID = "NewItemLnk";
						newLink.Text = _titleNewItemText != string.Empty ? _titleNewItemText : "New Item";
						newLink.Text = RenderUtil.RenderAccessKey( newLink.Text, newLink );
						newLink.CommandName = _newItemCommandName;
						//newLink.Command += new CommandEventHandler( NewItemOrFilter_Command );	//04/30/2006
						hdrNew.Controls.Add( newLink );

						if( _titleNewItemImageURL != null && _titleNewItemImageURL != string.Empty )
						{
							//ImageButton newImage = new ImageButton();
							//_new.ID = "NewItemImg";
							//_new.Command += new CommandEventHandler( NewItemOrFilter_Command );
							_new.ImageUrl = _titleNewItemImageURL;
							_new.CommandName = _newItemCommandName;
							hdrNew.Controls.Add( new LiteralControl( "&nbsp;" ) );
							hdrNew.Controls.Add( _new );
							////this.Page.RegisterRequiresPostBack( newImage );
						}
					}
				}

				if( _showFilterExpressionText && _filterExpressionText != string.Empty )
				{
					TableRow exprRow = new TableRow();
					exprRow.CssClass = _filterExpressionRowCssClass != string.Empty ? _filterExpressionRowCssClass : _titleRowCssClass;
					hdrContent.Rows.Add( hdrRow );

					TableCell exprCell = new TableCell();
					exprCell.ColumnSpan = hdrRow.Cells.Count;
					exprCell.CssClass = exprRow.CssClass;
					exprCell.Text = _filterExpressionText;
					exprRow.Cells.Add( exprCell );

					hdrContent.Rows.Add( exprRow );
				}

                titlebar.Controls.Add( hdrContent );
			}
            else
            {
				tt.InstantiateIn( titlebar );

				if( _showFilterExpressionText && _filterExpressionText != string.Empty && _filterExpressionTemplate != null )
				{
					PlaceHolder ctrl = (PlaceHolder)titlebar.FindControl( "FilterExpressionTemplate" );
					if( ctrl == null ) { ctrl = (PlaceHolder)this.Page.FindControl( "FilterExpressionTemplate" ); }
					if( ctrl != null )
					{
						sFilterExpressionContainer f = new sFilterExpressionContainer( _filterExpressionText );
						_filterExpressionTemplate.InstantiateIn( f );
						ctrl.Controls.Add( f );
						ctrl.DataBind();
					}
				}
            }

            return titleRow;
        }

		private TableRow AddFilterRow(bool isEmptyData, out GridViewRow headerRow)
		{
			_filterRow = new GridViewRow( -1, -1, DataControlRowType.Header, DataControlRowState.Normal );
			_filterRow.CssClass = _filterRowCssClass;

			headerRow = new GridViewRow( -1, -1, DataControlRowType.Header, DataControlRowState.Normal );
			headerRow.CssClass = this.HeaderStyle.CssClass;

			System.Drawing.Font font = new System.Drawing.Font( "Verdana", 10 );

			int index = 0;
			TableCell filterCell = null;
			foreach( DataControlField field in _displayColumns )
			{
				if( field.Visible )
				{
					if( field is ISDataControlField )
					{
						if( ( (ISDataControlField)field ).AllowFilter )
						{
							if( ( (ISDataControlField)field ).FilterTemplate == null )
							{
								filterCell = this.AddFilterCell( field, font );
								_filterRow.Cells.Add( filterCell );
							}
							else
							{
								filterCell = new TableCell();
								( (ISDataControlField)field ).FilterTemplate.InstantiateIn( filterCell );
								_filterRow.Cells.Add( filterCell );

								if( filterCell.Controls[0] is IGridViewFilterControl )
								{
									( (IGridViewFilterControl)filterCell.Controls[0] ).Field = field;
								}
							}

							//if( _filterFieldData.Count > 0 && filterCell.Controls[0] is IGridViewFilterControl )
							//{
							//    if( filterCell.Controls[0] is TextBox )
							//    {
							//        ( (TextBox)filterCell.Controls[0] ).Text = _filterFieldData[( (IGridViewFilterControl)filterCell.Controls[0] ).DataField];
							//    }
							//    else if( filterCell.Controls[0] is CheckBox )
							//    { }
							//    else if( filterCell.Controls[0] is DropDownList )
							//    {
							//        ( (DropDownList)filterCell.Controls[0] ).SelectedValue = _filterFieldData[( (IGridViewFilterControl)filterCell.Controls[0] ).DataField];
							//    }
							//}

							this.OnFilterColumnCreated( this, new sGridViewFilterColumnEventArgs( (ISDataControlField)field, filterCell.Controls[0] ) );
						}
						else
						{
							filterCell = null;
							_filterRow.Cells.Add( AddBlankCell( field, isEmptyData ) );
						}
					}
					else if( field is BoundField || field is CheckBoxField )
					{
						filterCell = this.AddFilterCell( field, font );
						_filterRow.Cells.Add( filterCell );
					}
					else
					{
						filterCell = null;
						_filterRow.Cells.Add( AddBlankCell( field, isEmptyData ) );
					}

					if( isEmptyData )
					{
						//filterCell.Controls.Add( new LiteralControl( string.Format( "<BR>{0}", field.HeaderText ) ) );
						TableCell c = new TableCell();
						c.Text = field.HeaderText;
						c.HorizontalAlign = HorizontalAlign.Center;
						headerRow.Cells.Add( c );
					}
				}

				index++;
			}

			if( !_showTitleRow )
			{
				LinkButton filter = new LinkButton();
				filter.Text = !string.IsNullOrEmpty( _filterItemText ) ? _filterItemText : "Filter";
				filter.CommandName = _filterCommandName;
				//filter.Command += new CommandEventHandler( NewItemOrFilter_Command );	//04/30/2006
				_filterRow.Cells[_filterRow.Cells.Count - 1].Controls.Add( filter );
			}


			return _filterRow;
		}

		private TableCell AddBlankCell(DataControlField field, bool isEmptyData)
		{
			TableCell c = new TableCell();
			if( isEmptyData )
			{
				c.Controls.Add( new LiteralControl( field.HeaderText ) );
			}
			else
			{
				c.Controls.Add( new LiteralControl( "&nbsp;" ) );
			}

			return c;
		}

		private TableCell AddFilterCell(DataControlField field, System.Drawing.Font font)
		{
			//string name = field.HeaderText == null || field.HeaderText == string.Empty ? index.ToString() : field.HeaderText;
			//string name = string.Empty;
			//if( field is BoundField || field is CheckBoxField )
			//{
			//    name = ( (BoundField)field ).DataField;
			//}

			TableCell cell = new TableCell();
			cell.CssClass = _filterRowCssClass;

			sFilterTextBox t = new sFilterTextBox();
			t.Width = MeasureDisplayStringWidth( ( (BoundField)field ).DataField, font );
			t.Field = field;
			cell.Controls.Add( t );


			//this code block works, but not sure how to handle bool search values.  need a three-state chkbox.
			//if( field is AutoGeneratedField && ((AutoGeneratedField)field).DataType == typeof(bool) )
			//{
			//    FilterCheckBox t = new FilterCheckBox();
			//    //t.ID = string.Format( "filter_{0}", name );
			//    t.Field = field;
			//    cell.Controls.Add( t );
			//}
			//else
			//{
			//    FilterTextBox t = new FilterTextBox();
			//    //t.ID = string.Format( "filter_{0}", name );
			//    t.Width = MeasureDisplayStringWidth( ( (BoundField)field ).DataField, font );
			//    t.Field = field;
			//    cell.Controls.Add( t );
			//}
			return cell;
		}

		private TableRow AddFilterExpressionRow(int cellCount)
		{
			GridViewRow exprRow = new GridViewRow( -1, -1, DataControlRowType.Header, DataControlRowState.Normal );
			TableCell exprCell = new TableCell();
			exprRow.CssClass = _filterExpressionRowCssClass != string.Empty ? _filterExpressionRowCssClass : _titleRowCssClass;
			exprCell.CssClass = exprRow.CssClass;
			exprCell.ColumnSpan = cellCount;
			exprCell.Text = _filterExpressionText;
			exprRow.Cells.Add( exprCell );
			return exprRow;
		}

		private int MeasureDisplayStringWidth(string text, System.Drawing.Font font)
		{
			const int width = 32;

			System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap( width, 1 );
			//System.Drawing.SizeF    size   = graphics.MeasureString( text, font );
			System.Drawing.Graphics anagra = System.Drawing.Graphics.FromImage( bitmap );

			int measured_width = 9 * ( text.Length + 1 );

			if( anagra != null )
			{
				anagra.Clear( System.Drawing.Color.White );
				anagra.DrawString( text + "|", font, System.Drawing.Brushes.Black, width - measured_width, -font.Height / 2 );

				for( int i = width - 1; i >= 0; i-- )
				{
					measured_width--;
					if( bitmap.GetPixel( i, 0 ).R != 255 )    // found a non-white pixel ?
						break;
				}
			}

			return measured_width;
		}

		[Obsolete("Not currently in use.", true)]
		private GridViewRow AddPagerRow(GridViewRow pagerRow, int cellCount)
		{
			GridViewRow footerRow = new GridViewRow( -1, -1, DataControlRowType.Footer, DataControlRowState.Normal );
			footerRow.CssClass = _footerRowCssClass;
			TableCell footerbar = new TableCell();
			footerbar.ColumnSpan = cellCount;
			footerRow.Cells.Add( footerbar );

			Table ftrContent = new Table();
			ftrContent.BorderWidth = Unit.Pixel( 0 );
			ftrContent.CellPadding = 0;
			ftrContent.CellSpacing = 0;
			ftrContent.CssClass = _footerRowCssClass;
			ftrContent.Rows.Add( pagerRow );

			footerbar.Controls.Add( ftrContent );

			return footerRow;
		}
		private GridViewRow AddFooterRow(int cellCount, bool isEmptyData)
		{
			ITemplate ft = !isEmptyData ? _footerTemplate : _emptyDataFooterTemplate;

			GridViewRow footerRow = new GridViewRow( -1, -1, DataControlRowType.Footer, DataControlRowState.Normal );
			footerRow.CssClass = !isEmptyData ? _footerRowCssClass : _emptyDataFooterRowCssClass;
			TableCell footerbar = new TableCell();
			footerbar.ColumnSpan = cellCount;
			footerRow.Cells.Add( footerbar );

			if( ft == null )
			{
				if( this.PageCount <= 1 && this.TotalRowCount > 0 )
				{
					Table ftrContent = new Table();
					ftrContent.BorderWidth = Unit.Pixel( 0 );
					ftrContent.CellPadding = 0;
					ftrContent.CellSpacing = 0;
					ftrContent.Width = new Unit( 100, UnitType.Percentage );
					ftrContent.CssClass = _footerRowCssClass;

					TableRow ftrRow = new TableRow();
					ftrRow.CssClass = _footerRowCssClass;
					ftrContent.Rows.Add( ftrRow );

					_footerTextCell = new TableCell();
					_footerTextCell.CssClass = _footerRowCssClass;
					//_footerTextCell.HorizontalAlign = HorizontalAlign.Right;
					_footerTextCell.Text = this.GetFooterText();
					ftrRow.Cells.Add( _footerTextCell );

					footerbar.Controls.Add( ftrContent );
				}
			}
			else
			{
				ft.InstantiateIn( footerbar );
			}

			return footerRow;
		}
		private string GetFooterText()
		{
			if( string.IsNullOrEmpty( _footerText ) )
			{
				return this.FormattedFooterText;
			}
			else
			{
				return _footerText;
			}
		}

		protected override bool OnBubbleEvent(object source, EventArgs e)
		{
			if( ( e is CommandEventArgs ) && HandleNewItemOrFilter( source, (CommandEventArgs)e ) )
			{
				return true;
			}
			else
			{
				return base.OnBubbleEvent( source, e );
			}
		}

		//removed this handler on 04/30/2006:
		//  OnBubbleEvent handles it w/in the .Net standard methodology
		//private void NewItemOrFilter_Command(object sender, CommandEventArgs e)
		//{
		//    HandleNewItemOrFilter( sender, e );
		//}

        private bool HandleNewItemOrFilter(object sender, CommandEventArgs e)
        {
            bool handled = false;

            switch( ( (CommandEventArgs)e ).CommandName )
            {
                case _newItemCommandName:
                {
                    OnNewItemClick( this, EventArgs.Empty );
                    handled = true;
                    break;
                }
                case _filterCommandName:
                {
					//if( !ExecuteFilter_DataView() )
					//{
					//    OnFilterClick( this, EventArgs.Empty );
					//}

					OnFilterClick( this, GetFilterArgs() );
                    handled = true;
                    break;
                }
            }

            return handled;
        }

		//private void SetFilterDataSource(PagedDataSource pds)
		//{
		//    _filterData = null;

		//    if( pds != null )
		//    {
		//        if( pds.DataSource is DataTable )
		//        {
		//            _filterData = ( (DataTable)pds.DataSource ).DefaultView;
		//        }
		//        else if( pds.DataSource is DataView )
		//        {
		//            _filterData = (DataView)pds.DataSource;
		//        }
		//        else if( pds.DataSource is DataSet )
		//        {
		//            _filterData = ( (DataSet)pds.DataSource ).Tables[0].DefaultView;
		//        }
		//    }
		//}

		private sGridViewFilterEventArgs GetFilterArgs()
		{
			List<IGridViewFilterControl> filterControls = new List<IGridViewFilterControl>();

			//if( _filterData == null )
			//{
			//    return false;
			//}


			#region build sql

			bool haveSql = false;
			StringBuilder sql = new StringBuilder();
			StringBuilder msg = new StringBuilder();
			IGridViewFilterControl filterControl;
			//int index = 0;
			bool ok = true;
			string searchValue = string.Empty;
			foreach( TableCell filterCell in _filterRow.Cells )
			{
				if( filterCell.Controls.Count > 0 &&
					filterCell.Controls[0] is IGridViewFilterControl &&
					( (IGridViewFilterControl)filterCell.Controls[0] ).HasText )
				{
					haveSql = true;
					ok = true;
					searchValue = string.Empty;

					filterControls.Add( (IGridViewFilterControl)filterCell.Controls[0] );
					filterControl = (IGridViewFilterControl)filterCell.Controls[0];

					//_filterFieldData[filterControl.DataField] = filterControl.GvfText;


					// bracket ([]) the field names in case they contain spaces
					if( filterControl.GvfText.IndexOf( "[dm]" ) > -1 )
					{
						if( sql.Length > 0 )	// index != _filterRow.Cells.Count - 1 && 
						{
							sql.AppendFormat( " {0} ", "AND" );
							msg.AppendFormat( " {0} ", "AND" );
						}

						sql.Append( filterControl.GvfText.Replace( "[dm]", string.Format( "[{0}]", filterControl.DataField ) ) );
						msg.Append( filterControl.GvfText.Replace( "[dm]", string.Format( "[{0}]", filterControl.Field.HeaderText ) ) );
						//msg.Append( filterControl.GvfText.Replace( "[dm]", filterControl.GvfText ) );
					}
					else
					{
						switch( filterControl.DataType )
						{
							case TypeCode.String:
							{
								break;
							}
							case TypeCode.Boolean:
							{
								bool x = false;
								ok = bool.TryParse( filterControl.GvfValue, out x );
								break;
							}
							case TypeCode.Int32:
							{
								int x = -1;
								ok = Int32.TryParse( filterControl.GvfValue, out x );
								break;
							}
							case TypeCode.DateTime:
							{
								DateTime x = DateTime.MinValue;
								ok = DateTime.TryParse( filterControl.GvfValue, out x );
								break;
							}
							default:
							{
								//( (FilterOptions)mch.FilterTextBox.Tag ).ComparisonOperator = comp;
								//if( comp.ToLower() == "like" ) { comp = ">="; }
								//else if( comp.ToLower() == "not like" ) { comp = ">"; }
								ok = false;
								break;
							}
						}


						if( ok )
						{
							if( sql.Length > 0 )	// index != _filterRow.Cells.Count - 1 && 
							{
								sql.AppendFormat( " {0} ", "AND" );
								msg.AppendFormat( " {0} ", "AND" );
							}

							if( filterControl.ComparisonOperator.ToLower() == "like" )
							{
								sql.AppendFormat( "[{0}] LIKE {2}*{1}*{2}", filterControl.DataField, filterControl.GvfValue, filterControl.Delimeter );
								msg.AppendFormat( "[{0}] {1} {3}*{2}*{3}", filterControl.Field.HeaderText, filterControl.ComparisonOperatorText, filterControl.GvfText, filterControl.Delimeter );
							}
							else if( filterControl.ComparisonOperator.ToLower() == "not like" )
							{
								sql.AppendFormat( "[{0}] NOT LIKE {2}*{1}*{2}", filterControl.DataField, filterControl.GvfValue, filterControl.Delimeter );
								msg.AppendFormat( "[{0}] {1} {3}*{2}*{3}", filterControl.Field.HeaderText, filterControl.ComparisonOperatorText, filterControl.GvfText, filterControl.Delimeter );
							}
							else
							{
								sql.AppendFormat( "[{0}] {1} {3}{2}{3}",
									filterControl.DataField, filterControl.ComparisonOperator, filterControl.GvfValue, filterControl.Delimeter );
								msg.AppendFormat( "[{0}] {1} {3}{2}{3}",
									filterControl.Field.HeaderText, filterControl.ComparisonOperatorText, filterControl.GvfText, filterControl.Delimeter );
							}
						}
					}
				}

				//index++;
			}

			#endregion

			if( haveSql )
			{
				_filterExpressionText = msg.ToString();
				return new sGridViewFilterEventArgs( filterControls, sql.ToString(), _filterExpressionText );
			}
			else
			{
				_filterExpressionText = string.Empty;
				return sGridViewFilterEventArgs.Empty;
			}


			#region execute sql (filter or typeahead-search)

			//////using haveSql instead of sql.Length b/c above columns-loop won't clear last char from sql
			////if( haveSql )
			////{
			////    try
			////    {
			////        _filterData.RowFilter = sql.ToString();
			////        //this.DataBind();
			////        //UpdateStatusInfo( true, "  ( " + msg.ToString() + " )" );
			////    }
			////    catch( Exception ex )
			////    {
			////        string err = string.Format( "Error in filter expression: {0}\r\nMessage: {1}", msg.ToString(), ex.Message );
			////        ///MessageBox.Show( this, err, "Error filtering data", MessageBoxButtons.OK, MessageBoxIcon.Exclamation );
			////    }
			////}
			////else
			////{
			////    //UpdateStatusInfo( _isFiltered );
			////}

			#endregion

			//return haveSql;
		}


		#region events

		protected override void OnRowEditing(GridViewEditEventArgs e)
		{
			dbg.WriteLine( "OnRowEditing" );
			base.OnRowEditing( e );
		}
		protected override void OnRowDeleting(GridViewDeleteEventArgs e)
		{
			dbg.WriteLine( "OnRowDeleting" );
			base.OnRowDeleting( e );
		}
		protected override void OnRowDeleted(GridViewDeletedEventArgs e)
		{
			dbg.WriteLine( "OnRowDeleted" );
			base.OnRowDeleted( e );
		}
		protected override void OnRowCommand(GridViewCommandEventArgs e)
		{
			dbg.WriteLine( "OnRowCommand" );
			base.OnRowCommand( e );
		}
		#endregion
		#endregion


		#region bunkey
		//#region IPostBackDataHandler Members

		//public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
		//{
		//    string postedValue = postCollection[postDataKey];
		//    return postedValue != string.Empty;
		//}

		//public void RaisePostDataChangedEvent()
		//{
		//    throw new Exception( "The method or operation is not implemented." );
		//}

		//protected override void OnPreRender(EventArgs e)
		//{
		//    base.OnPreRender( e );
		//}

		//protected override void Render(HtmlTextWriter writer)
		//{
		//    this.Page.ClientScript.RegisterForEventValidation( _fil.ID );
		//    base.Render( writer );
		//}


		//protected override void RaisePostBackEvent(string eventArgument)
		//{
		//    base.RaisePostBackEvent( eventArgument );
		//}

		//#endregion
		#endregion


		#region IWebExtra Members
		public string Tag
		{
			get { return _tag; }
			set { _tag = value; }
		}

		[Browsable( false )]
		public object TagObj
		{
			get { return _tagObject; }
			set { _tagObject = value; }
		}
		#endregion
	}


	public class sFilterExpressionContainer : Control, INamingContainer
	{
		private string _filterExpression = string.Empty;

		internal sFilterExpressionContainer (string filterExpression)
		{
			_filterExpression = filterExpression;
		}
		public string FilterExpression
		{
			get
			{
				return _filterExpression;
			}
		}
	}



	#region GridViewFilter Event
	public delegate void sGridViewFilterEventHandler(object sender, sGridViewFilterEventArgs e);

	public class sGridViewFilterEventArgs : EventArgs
	{
		private List<IGridViewFilterControl> _filterControls = null;
		private string _filterExpression = string.Empty;
		private string _filterFormattedExpression = string.Empty;

		new public static readonly sGridViewFilterEventArgs Empty;
		static sGridViewFilterEventArgs()
		{
			Empty = new sGridViewFilterEventArgs();
		}

		public sGridViewFilterEventArgs() { }

		internal sGridViewFilterEventArgs(List<IGridViewFilterControl> filterControls, string filterExpression, string filterFormattedExpression)
		{
			_filterControls = filterControls;
			_filterExpression = filterExpression;
			_filterFormattedExpression = filterFormattedExpression;
		}

		public List<IGridViewFilterControl> FilterControls { get { return _filterControls; } }

		public string FilterExpression { get { return _filterExpression; } }

		public string FilterFormattedExpression { get { return _filterFormattedExpression; } }
	}



	public delegate void sGridViewFilterColumnEventHandler(object sender, sGridViewFilterColumnEventArgs e);

	public class sGridViewFilterColumnEventArgs : EventArgs
	{
		private ISDataControlField _column = null;
		private Control _filterControl = null;

		new public static readonly sGridViewFilterColumnEventArgs Empty;
		static sGridViewFilterColumnEventArgs()
		{
			Empty = new sGridViewFilterColumnEventArgs();
		}

		public sGridViewFilterColumnEventArgs() { }

		internal sGridViewFilterColumnEventArgs(ISDataControlField column, Control filterControl)
		{
			_column = column;
			_filterControl = filterControl;
		}

		public ISDataControlField Column { get { return _column; } }
		public Control FilterControl { get { return _filterControl; } }
	}
	#endregion


	#region IGridViewFilterControl
	public interface IGridViewFilterControl
	{
		DataControlField Field { get; set; }
		string DataField { get; set; }
		bool HasText { get; }
		string GvfText { get; }
		string GvfValue { get; }
		bool IsDateTime { get; }
		DateTime GvfDateTime { get; }
		TypeCode DataType { get; }
		string ComparisonOperator { get; set; }
		string ComparisonOperatorText { get; set; }
		string Delimeter { get; set; }
	}
	public class sFilterTextBox : TextBox, IGridViewFilterControl
	{
		private DataControlField _field;
		private string _dataField = null;
		private DateTime _dateTime = DateTime.Now;
		private TypeCode _dataType = TypeCode.String;
		private bool _allowDataTypeOverride = true;
		private string _comparisonOperator = null;
		private string _comparisonOperatorText = null;
		private string _delimeter = "'";

		public DataControlField Field { get { return _field; } set { _field = value; } }
		public string DataField { get { return !string.IsNullOrEmpty( _dataField ) ? _dataField : ( (BoundField)_field ).DataField; } set { _dataField = value; } }
		public bool HasText { get { return base.Text != string.Empty; } }
		public string GvfText { get { return base.Text; } }
		public string GvfValue { get { return base.Text; } }
		public bool IsDateTime
		{
			get
			{
				try
				{
					_dateTime = DateTime.Parse( base.Text );
					_dataType = TypeCode.DateTime;
					_allowDataTypeOverride = false;
					return true;
				}
				catch
				{
					return false;
				}
			}
		}
		public DateTime GvfDateTime { get { return _dateTime; } }
		public TypeCode DataType
		{
			get
			{
				if( _field is AutoGeneratedField && _allowDataTypeOverride )
				{
					return Type.GetTypeCode( ( (AutoGeneratedField)_field ).DataType );
				}
				else if( _field is ISDataControlField )
				{
					return ( (ISDataControlField)_field ).FilterDataType;
				}
				else
				{
					return _dataType;
				}
			}
		}
		//TODO: set up this same structure for Delimiter if "'" isn't good default
		public string ComparisonOperator
		{
			get
			{
				if( string.IsNullOrEmpty( _comparisonOperator ) )
				{
					switch( this.DataType )
					{
						case TypeCode.String:
						{
							_comparisonOperator = "like";
							break;
						}
						default:
						{
							_comparisonOperator = "=";
							break;
						}
					}
				}

				return _comparisonOperator;
			}
			set { _comparisonOperator = value; }
		}
		public string ComparisonOperatorText { get { return !string.IsNullOrEmpty( _comparisonOperatorText ) ? _comparisonOperatorText : _comparisonOperator; } set { _comparisonOperatorText = value; } }
		public string Delimeter { get { return _delimeter; } set { _delimeter = value; } }
	}
	public class sFilterDropDownList : DropDownList, IGridViewFilterControl
	{
		private DataControlField _field;
		private string _dataField = null;
		private TypeCode _dataType = TypeCode.String;
		private string _comparisonOperator = "=";
		private string _comparisonOperatorText = null;
		private string _delimeter = "'";
		private bool _evaluateValueForText = false;

		public DataControlField Field { get { return _field; } set { _field = value; } }
		public string DataField { get { return !string.IsNullOrEmpty( _dataField ) ? _dataField : ( (BoundField)_field ).DataField; } set { _dataField = value; } }
		public bool HasText { get { return this.HasSelectedItem; } }
		public string GvfText { get { return this.HasSelectedItem ? _evaluateValueForText ? base.SelectedItem.Value : base.SelectedItem.Text : string.Empty; } }
		public string GvfValue { get { return this.HasSelectedItem ? base.SelectedItem.Value : string.Empty; } }
		public bool IsDateTime { get { return false; } }
		public DateTime GvfDateTime { get { return DateTime.Now; } }
		public TypeCode DataType
		{
			get
			{
				if( _field is AutoGeneratedField )
				{
					return Type.GetTypeCode( ( (AutoGeneratedField)_field ).DataType );
				}
				else if( _field is ISDataControlField )
				{
					return ( (ISDataControlField)_field ).FilterDataType;
				}
				else
				{
					return _dataType;
				}
			}
		}
		public string ComparisonOperator { get { return _comparisonOperator; } set { _comparisonOperator = value; } }
		public string ComparisonOperatorText { get { return !string.IsNullOrEmpty( _comparisonOperatorText ) ? _comparisonOperatorText : _comparisonOperator; } set { _comparisonOperatorText = value; } }
		public string Delimeter { get { return _delimeter; } set { _delimeter = value; } }
		private bool HasSelectedItem
		{
			get
			{
				string text = string.Empty;
				if( base.SelectedItem != null )
				{
					text = _evaluateValueForText ? base.SelectedItem.Value : base.SelectedItem.Text;
				}

				return text != string.Empty;
			}
		}
		public bool EvaluateValueForText { get { return _evaluateValueForText; } set { _evaluateValueForText = value; } }
	}
	public class sFilterCheckBox : CheckBox, IGridViewFilterControl
	{
		private DataControlField _field;
		private string _dataField = null;
		private TypeCode _dataType = TypeCode.Boolean;
		private string _comparisonOperator = "=";
		private string _comparisonOperatorText = null;
		private string _delimeter = string.Empty;

		public DataControlField Field { get { return _field; } set { _field = value; } }
		public string DataField { get { return !string.IsNullOrEmpty( _dataField ) ? _dataField : ( (BoundField)_field ).DataField; } set { _dataField = value; } }
		public bool HasText { get { return true; } }
		public string GvfText { get { return base.Checked.ToString(); } }
		public string GvfValue { get { return base.Checked.ToString(); } }
		public bool IsDateTime { get { return false; } }
		public DateTime GvfDateTime { get { return DateTime.Now; } }
		public TypeCode DataType
		{
			get
			{
				if( _field is AutoGeneratedField )
				{
					return Type.GetTypeCode( ( (AutoGeneratedField)_field ).DataType );
				}
				else if( _field is ISDataControlField )
				{
					return ( (ISDataControlField)_field ).FilterDataType;
				}
				else
				{
					return _dataType;
				}
			}
		}
		public string ComparisonOperator { get { return _comparisonOperator; } set { _comparisonOperator = value; } }
		public string ComparisonOperatorText { get { return !string.IsNullOrEmpty( _comparisonOperatorText ) ? _comparisonOperatorText : _comparisonOperator; } set { _comparisonOperatorText = value; } }
		public string Delimeter { get { return _delimeter; } set { _delimeter = value; } }
	}
	#endregion


	#region ISDataControlField
	public interface ISDataControlField
	{
		int DisplayIndex { get; set; }
		bool AllowFilter { get; set; }
		TypeCode FilterDataType { get; set; }
		ITemplate FilterTemplate { get; set; }
	}
	//BoundField-->DataField
	public class sBoundField : System.Web.UI.WebControls.BoundField, ISDataControlField
	{
		private int _displayIndex = Int32.MinValue;
		private bool _allowFilter = true;
		private TypeCode _filterDataType = TypeCode.String;
		private ITemplate _filterTemplate = null;

		public int DisplayIndex
		{
			get { return _displayIndex; }
			set { _displayIndex = value; }
		}
		public bool AllowFilter
		{
			get { return _allowFilter; }
			set { _allowFilter = value; }
		}
		public TypeCode FilterDataType
		{
			get { return _filterDataType; }
			set { _filterDataType = value; }
		}
		public ITemplate FilterTemplate
		{
			get { return _filterTemplate; }
			set { _filterTemplate = value; }
		}
	}
	//ButtonField-->DataTextField
	public class sButtonField : System.Web.UI.WebControls.ButtonField, ISDataControlField
    {
		private int _displayIndex = Int32.MinValue;
        private bool _allowFilter = false;
		private TypeCode _filterDataType = TypeCode.String;
		private ITemplate _filterTemplate = null;

		public int DisplayIndex
		{
			get { return _displayIndex; }
			set { _displayIndex = value; }
		}
		public bool AllowFilter
		{
			get { return _allowFilter; }
			set { _allowFilter = value; }
		}
		public TypeCode FilterDataType
		{
			get { return _filterDataType; }
			set { _filterDataType = value; }
		}
		public ITemplate FilterTemplate
		{
			get { return _filterTemplate; }
			set { _filterTemplate = value; }
		}
	}
	//BoundField-->DataField
	public class sCheckBoxField : System.Web.UI.WebControls.CheckBoxField, ISDataControlField
    {
		private int _displayIndex = Int32.MinValue;
        private bool _allowFilter = true;
		private TypeCode _filterDataType = TypeCode.Boolean;
		private ITemplate _filterTemplate = null;

		public int DisplayIndex
		{
			get { return _displayIndex; }
			set { _displayIndex = value; }
		}
		public bool AllowFilter
		{
			get { return _allowFilter; }
			set { _allowFilter = value; }
		}
		public TypeCode FilterDataType
		{
			get { return _filterDataType; }
			set { _filterDataType = value; }
		}
		public ITemplate FilterTemplate
		{
			get { return _filterTemplate; }
			set { _filterTemplate = value; }
		}
	}
	//CommandField-->special
	public class sCommandField : System.Web.UI.WebControls.CommandField, ISDataControlField
    {
		private int _displayIndex = Int32.MinValue;
        private bool _allowFilter = false;
		private TypeCode _filterDataType = TypeCode.String;
		private ITemplate _filterTemplate = null;

		public int DisplayIndex
		{
			get { return _displayIndex; }
			set { _displayIndex = value; }
		}
		public bool AllowFilter
		{
			get { return _allowFilter; }
			set { _allowFilter = value; }
		}
		public TypeCode FilterDataType
		{
			get { return _filterDataType; }
			set { _filterDataType = value; }
		}
		public ITemplate FilterTemplate
		{
			get { return _filterTemplate; }
			set { _filterTemplate = value; }
		}
	}
	//HyperLinkField-->DataTextField
	public class sHyperLinkField : System.Web.UI.WebControls.HyperLinkField, ISDataControlField
    {
		private int _displayIndex = Int32.MinValue;
        private bool _allowFilter = false;
		private TypeCode _filterDataType = TypeCode.String;
		private ITemplate _filterTemplate = null;

		public int DisplayIndex
		{
			get { return _displayIndex; }
			set { _displayIndex = value; }
		}
		public bool AllowFilter
		{
			get { return _allowFilter; }
			set { _allowFilter = value; }
		}
		public TypeCode FilterDataType
		{
			get { return _filterDataType; }
			set { _filterDataType = value; }
		}
		public ITemplate FilterTemplate
		{
			get { return _filterTemplate; }
			set { _filterTemplate = value; }
		}
	}
	//ImageField-->DataImageUrlField
	public class sImageField : System.Web.UI.WebControls.ImageField, ISDataControlField
    {
		private int _displayIndex = Int32.MinValue;
        private bool _allowFilter = false;
		private TypeCode _filterDataType = TypeCode.String;
		private ITemplate _filterTemplate = null;

		public int DisplayIndex
		{
			get { return _displayIndex; }
			set { _displayIndex = value; }
		}
		public bool AllowFilter
		{
			get { return _allowFilter; }
			set { _allowFilter = value; }
		}
		public TypeCode FilterDataType
		{
			get { return _filterDataType; }
			set { _filterDataType = value; }
		}
		public ITemplate FilterTemplate
		{
			get { return _filterTemplate; }
			set { _filterTemplate = value; }
		}
	}
	//TemplateField-->special
	public class sTemplateField : System.Web.UI.WebControls.TemplateField, ISDataControlField
	{
		private int _displayIndex = Int32.MinValue;
		private bool _allowFilter = false;
		private TypeCode _filterDataType = TypeCode.String;
		private ITemplate _filterTemplate = null;

		public int DisplayIndex
		{
			get { return _displayIndex; }
			set { _displayIndex = value; }
		}
		public bool AllowFilter
		{
			get { return _allowFilter; }
			set { _allowFilter = value; }
		}
		public TypeCode FilterDataType
		{
			get { return _filterDataType; }
			set { _filterDataType = value; }
		}
		public ITemplate FilterTemplate
		{
			get { return _filterTemplate; }
			set { _filterTemplate = value; }
		}
	}
	public class sCommandTemplateField : System.Web.UI.WebControls.TemplateField, ISDataControlField
	{
		private sIconTemplate _iconTemplate = null;

		public sCommandTemplateField()
		{
			_iconTemplate = new sIconTemplate();
			this.ItemTemplate = _iconTemplate;
		}

		private int _displayIndex = Int32.MinValue;
		private bool _allowFilter = false;
		private TypeCode _filterDataType = TypeCode.String;
		private ITemplate _filterTemplate = null;

		private string _alternateSecurityDescriptorKey = string.Empty;

		public bool ShowSelectButton { get { return _iconTemplate.ShowSelectButton; } set { _iconTemplate.ShowSelectButton = value; } }
		public bool ShowInsertButton { get { return _iconTemplate.ShowInsertButton; } set { _iconTemplate.ShowInsertButton = value; } }
		public bool ShowEditButton { get { return _iconTemplate.ShowEditButton; } set { _iconTemplate.ShowEditButton = value; } }
		public bool ShowUpdateButton { get { return _iconTemplate.ShowUpdateButton; } set { _iconTemplate.ShowUpdateButton = value; } }
		public bool ShowDeleteButton { get { return _iconTemplate.ShowDeleteButton; } set { _iconTemplate.ShowDeleteButton = value; } }
		public bool ShowCancelButton { get { return _iconTemplate.ShowCancelButton; } set { _iconTemplate.ShowCancelButton = value; } }

		public string SelectButtonCommandArgument { get { return _iconTemplate.SelectButtonCommandArgument; } set { _iconTemplate.SelectButtonCommandArgument = value; } }
		public string InsertButtonCommandArgument { get { return _iconTemplate.InsertButtonCommandArgument; } set { _iconTemplate.InsertButtonCommandArgument = value; } }
		public string EditButtonCommandArgument { get { return _iconTemplate.EditButtonCommandArgument; } set { _iconTemplate.EditButtonCommandArgument = value; } }
		public string UpdateButtonCommandArgument { get { return _iconTemplate.UpdateButtonCommandArgument; } set { _iconTemplate.UpdateButtonCommandArgument = value; } }
		public string DeleteButtonCommandArgument { get { return _iconTemplate.DeleteButtonCommandArgument; } set { _iconTemplate.DeleteButtonCommandArgument = value; } }
		public string CancelButtonCommandArgument { get { return _iconTemplate.CancelButtonCommandArgument; } set { _iconTemplate.CancelButtonCommandArgument = value; } }

		public string SelectImageUrl { get { return _iconTemplate.SelectImageUrl; } set { _iconTemplate.SelectImageUrl = value; } }
		public string InsertImageUrl { get { return _iconTemplate.InsertImageUrl; } set { _iconTemplate.InsertImageUrl = value; } }
		public string EditImageUrl { get { return _iconTemplate.EditImageUrl; } set { _iconTemplate.EditImageUrl = value; } }
		public string UpdateImageUrl { get { return _iconTemplate.UpdateImageUrl; } set { _iconTemplate.UpdateImageUrl = value; } }
		public string DeleteImageUrl { get { return _iconTemplate.DeleteImageUrl; } set { _iconTemplate.DeleteImageUrl = value; } }
		public string CancelImageUrl { get { return _iconTemplate.CancelImageUrl; } set { _iconTemplate.CancelImageUrl = value; } }

		public string SelectButtonToolTip { get { return _iconTemplate.SelectButtonToolTip; } set { _iconTemplate.SelectButtonToolTip = value; } }
		public string InsertButtonToolTip { get { return _iconTemplate.InsertButtonToolTip; } set { _iconTemplate.InsertButtonToolTip = value; } }
		public string EditButtonToolTip { get { return _iconTemplate.EditButtonToolTip; } set { _iconTemplate.EditButtonToolTip = value; } }
		public string UpdateButtonToolTip { get { return _iconTemplate.UpdateButtonToolTip; } set { _iconTemplate.UpdateButtonToolTip = value; } }
		public string DeleteButtonToolTip { get { return _iconTemplate.DeleteButtonToolTip; } set { _iconTemplate.DeleteButtonToolTip = value; } }
		public string CancelButtonToolTip { get { return _iconTemplate.CancelButtonToolTip; } set { _iconTemplate.CancelButtonToolTip = value; } }

		public string Spacer { get { return _iconTemplate.Spacer; } set { _iconTemplate.Spacer = value; } }

		public string AlternateSecurityDescriptorKey { get { return _alternateSecurityDescriptorKey; } set { _alternateSecurityDescriptorKey = value; } }


		//public string SelectButtonCssClass { get { return _iconTemplate.SelectButtonCssClass; } set { _iconTemplate.SelectButtonCssClass = value; } }
		//public string InsertButtonCssClass { get { return _iconTemplate.InsertButtonCssClass; } set { _iconTemplate.InsertButtonCssClass = value; } }
		//public string EditButtonCssClass { get { return _iconTemplate.EditButtonCssClass; } set { _iconTemplate.EditButtonCssClass = value; } }
		//public string DeleteButtonCssClass { get { return _iconTemplate.DeleteButtonCssClass; } set { _iconTemplate.DeleteButtonCssClass = value; } }

		//public bool ShowCustomButton1 { get { return _iconTemplate.ShowCustomButton1; } set { _iconTemplate.ShowCustomButton1 = value; } }
		//public bool ShowCustomButton2 { get { return _iconTemplate.ShowCustomButton2; } set { _iconTemplate.ShowCustomButton2 = value; } }
		//public bool ShowCustomButton3 { get { return _iconTemplate.ShowCustomButton3; } set { _iconTemplate.ShowCustomButton3 = value; } }

		//public string CustomButton1ImageUrl { get { return _iconTemplate.CustomButton1ImageUrl; } set { _iconTemplate.CustomButton1ImageUrl = value; } }
		//public string CustomButton2ImageUrl { get { return _iconTemplate.CustomButton2ImageUrl; } set { _iconTemplate.CustomButton2ImageUrl = value; } }
		//public string CustomButton3ImageUrl { get { return _iconTemplate.CustomButton3ImageUrl; } set { _iconTemplate.CustomButton3ImageUrl = value; } }

		//public string CustomButton1ToolTip { get { return _iconTemplate.CustomButton1ToolTip; } set { _iconTemplate.CustomButton1ToolTip = value; } }
		//public string CustomButton2ToolTip { get { return _iconTemplate.CustomButton2ToolTip; } set { _iconTemplate.CustomButton2ToolTip = value; } }
		//public string CustomButton3ToolTip { get { return _iconTemplate.CustomButton3ToolTip; } set { _iconTemplate.CustomButton3ToolTip = value; } }

		//public string CustomButton1CommandName { get { return _iconTemplate.CustomButton1CommandName; } set { _iconTemplate.CustomButton1CommandName = value; } }
		//public string CustomButton2CommandName { get { return _iconTemplate.CustomButton2CommandName; } set { _iconTemplate.CustomButton2CommandName = value; } }
		//public string CustomButton3CommandName { get { return _iconTemplate.CustomButton3CommandName; } set { _iconTemplate.CustomButton3CommandName = value; } }


		public int DisplayIndex
		{
			get { return _displayIndex; }
			set { _displayIndex = value; }
		}
		public bool AllowFilter
		{
			get { return _allowFilter; }
			set { _allowFilter = value; }
		}
		public TypeCode FilterDataType
		{
			get { return _filterDataType; }
			set { _filterDataType = value; }
		}
		public ITemplate FilterTemplate
		{
			get { return _filterTemplate; }
			set { _filterTemplate = value; }
		}
	}
	#region IconTemplate : ITemplate
	public class sIconTemplate : ITemplate
	{
		private bool _showSelect = false;
		private bool _showInsert = false;
		private bool _showEdit = false;
		private bool _showUpdate = false;
		private bool _showDelete = false;
		private bool _showCancel = false;

		private string _selectCommandArg = string.Empty;
		private string _insertCommandArg = string.Empty;
		private string _editCommandArg = string.Empty;
		private string _updateCommandArg = string.Empty;
		private string _deleteCommandArg = string.Empty;
		private string _cancelCommandArg = string.Empty;

		private string _selectImageUrl = string.Empty;
		private string _insertImageUrl = string.Empty;
		private string _editImageUrl = string.Empty;
		private string _updateImageUrl = string.Empty;
		private string _deleteImageUrl = string.Empty;
		private string _cancelImageUrl = string.Empty;

		private string _selectToolTip = "View";
		private string _insertToolTip = "New";
		private string _editToolTip = "Edit";
		private string _updateToolTip = "Update";
		private string _deleteToolTip = "Delete";
		private string _cancelToolTip = "Cancel";

		private string _spacer = " ";

		public sIconTemplate() { }

		public bool ShowSelectButton { get { return _showSelect; } set { _showSelect = value; } }
		public bool ShowInsertButton { get { return _showInsert; } set { _showInsert = value; } }
		public bool ShowEditButton { get { return _showEdit; } set { _showEdit = value; } }
		public bool ShowUpdateButton { get { return _showUpdate; } set { _showUpdate = value; } }
		public bool ShowDeleteButton { get { return _showDelete; } set { _showDelete = value; } }
		public bool ShowCancelButton { get { return _showCancel; } set { _showCancel = value; } }

		public string SelectButtonCommandArgument { get { return _selectCommandArg; } set { _selectCommandArg = value; } }
		public string InsertButtonCommandArgument { get { return _insertCommandArg; } set { _insertCommandArg = value; } }
		public string EditButtonCommandArgument { get { return _editCommandArg; } set { _editCommandArg = value; } }
		public string UpdateButtonCommandArgument { get { return _updateCommandArg; } set { _updateCommandArg = value; } }
		public string DeleteButtonCommandArgument { get { return _deleteCommandArg; } set { _deleteCommandArg = value; } }
		public string CancelButtonCommandArgument { get { return _cancelCommandArg; } set { _cancelCommandArg = value; } }

		public string SelectImageUrl { get { return _selectImageUrl; } set { _selectImageUrl = value; } }
		public string InsertImageUrl { get { return _insertImageUrl; } set { _insertImageUrl = value; } }
		public string EditImageUrl { get { return _editImageUrl; } set { _editImageUrl = value; } }
		public string UpdateImageUrl { get { return _updateImageUrl; } set { _updateImageUrl = value; } }
		public string DeleteImageUrl { get { return _deleteImageUrl; } set { _deleteImageUrl = value; } }
		public string CancelImageUrl { get { return _cancelImageUrl; } set { _cancelImageUrl = value; } }

		public string SelectButtonToolTip { get { return _selectToolTip; } set { _selectToolTip = value; } }
		public string InsertButtonToolTip { get { return _insertToolTip; } set { _insertToolTip = value; } }
		public string EditButtonToolTip { get { return _editToolTip; } set { _editToolTip = value; } }
		public string UpdateButtonToolTip { get { return _updateToolTip; } set { _updateToolTip = value; } }
		public string DeleteButtonToolTip { get { return _deleteToolTip; } set { _deleteToolTip = value; } }
		public string CancelButtonToolTip { get { return _cancelToolTip; } set { _cancelToolTip = value; } }

		public string Spacer { get { return _spacer; } set { _spacer = value; } }

		public void InstantiateIn(System.Web.UI.Control container)
		{
			List<Control> c = new List<Control>();

			if( _showSelect )
			{
				ImageButton sel_btn = new ImageButton();
				sel_btn.DataBinding += new EventHandler( this.Button_DataBinding );
				//sel_btn.Visible = _showSelect;

				sel_btn.ImageUrl = _selectImageUrl;
				sel_btn.CommandArgument = _selectCommandArg;
				sel_btn.AlternateText = _selectToolTip;
				sel_btn.ToolTip = _selectToolTip;
				sel_btn.CommandName = "select";

				c.Add( sel_btn );
				//container.Controls.Add( sel_btn );
			}
			if( _showInsert )
			{
				ImageButton ins_btn = new ImageButton();
				ins_btn.DataBinding += new EventHandler( this.Button_DataBinding );
				//edt_btn.Visible = _showEdit;

				ins_btn.ImageUrl = _insertImageUrl;
				ins_btn.CommandArgument = _insertCommandArg;
				ins_btn.AlternateText = _insertToolTip;
				ins_btn.ToolTip = _insertToolTip;
				ins_btn.CommandName = "insert";

				c.Add( ins_btn );
				//container.Controls.Add( ins_btn );
			}
			if( _showEdit )
			{
				ImageButton edt_btn = new ImageButton();
				edt_btn.DataBinding += new EventHandler( this.Button_DataBinding );
				//edt_btn.Visible = _showEdit;

				edt_btn.ImageUrl = _editImageUrl;
				edt_btn.CommandArgument = _editCommandArg;
				edt_btn.AlternateText = _editToolTip;
				edt_btn.ToolTip = _editToolTip;
				edt_btn.CommandName = "edit";

				c.Add( edt_btn );
				//container.Controls.Add( edt_btn );
			}
			if( _showUpdate )
			{
				ImageButton updt_btn = new ImageButton();
				updt_btn.DataBinding += new EventHandler( this.Button_DataBinding );
				//updt_btn.Visible = _showUpdate;

				updt_btn.ImageUrl = _updateImageUrl;
				updt_btn.CommandArgument = _updateCommandArg;
				updt_btn.AlternateText = _updateToolTip;
				updt_btn.ToolTip = _updateToolTip;
				updt_btn.CommandName = "update";

				c.Add( updt_btn );
				//container.Controls.Add( updt_btn );
			}
			if( _showDelete )
			{
				ImageButton del_btn = new ImageButton();
				del_btn.DataBinding += new EventHandler( this.Button_DataBinding );
				//del_btn.Visible = _showEdit;

				del_btn.ImageUrl = _deleteImageUrl;
				del_btn.CommandArgument = _deleteCommandArg;
				del_btn.AlternateText = _deleteToolTip;
				del_btn.ToolTip = _deleteToolTip;
				del_btn.CommandName = "delete";

				c.Add( del_btn );
				//container.Controls.Add( del_btn );
			}
			if( _showCancel )
			{
				ImageButton cncl_btn = new ImageButton();
				cncl_btn.DataBinding += new EventHandler( this.Button_DataBinding );
				//cncl_btn.Visible = _showCancel;

				cncl_btn.ImageUrl = _cancelImageUrl;
				cncl_btn.CommandArgument = _cancelCommandArg;
				cncl_btn.AlternateText = _cancelToolTip;
				cncl_btn.ToolTip = _cancelToolTip;
				cncl_btn.CommandName = "cancel";

				c.Add( cncl_btn );
				//container.Controls.Add( cncl_btn );
			}

			for( int i = 0; i < c.Count - 1; i++ )
			{
				container.Controls.Add( c[i] );
				if( !string.IsNullOrEmpty( _spacer ) )
				{
					container.Controls.Add( new LiteralControl( _spacer ) );
				}
			}
			if( ( c.Count - 1 ) > -1 )
			{
				container.Controls.Add( c[c.Count - 1] );
			}


			if( container is TableCell )
			{
				( (TableCell)container ).Width = Unit.Percentage( 1 );
				//if( container.Controls.Count == 0 )
				//{
				//    ( (TableCell)container ).Width = Unit.Percentage( 1 );
				//}
			}

			////container.Controls.Add( new LiteralControl( "&nbsp;" ) );
			//if( container is TableCell )
			//{
			//    if( _allowed )
			//    {
			//        ( (TableCell)container ).Width = Unit.Pixel( 17 );
			//    }
			//    else
			//    {
			//        ( (TableCell)container ).Width = Unit.Pixel( 1 );
			//    }
			//    //((TableCell)container).Wrap = false;
			//}
		}


		private void Button_DataBinding(object sender, EventArgs e)
		{
			ImageButton b = (ImageButton)sender;
			// b.Width = Unit.Pixel( (int)(b.Width.Value + Unit.Pixel( 3 ).Value) );

			if( string.IsNullOrEmpty( b.CommandArgument ) )
			{
				GridViewRow container = (GridViewRow)b.NamingContainer;
				b.CommandArgument = DataBinder.Eval( container, "RowIndex" ).ToString();
			}

			b.Page.ClientScript.RegisterForEventValidation( b.ID, b.CommandArgument );
		}
	}
	#endregion
	public enum mCommandFieldCommandType
	{
		Select,
		Insert,
		Edit,
		Update,
		Delete,
		Cancel
	}
	#endregion



	internal class RecordRightsPermissionsCacheHandler
	{
		private StateBag _viewstate = null;
		private List<RecordRightsPermissionsSet> _rights = new List<RecordRightsPermissionsSet>();

		private const string _rrList = "__pc1";
		private const string _rrSelect = "__pc2";
		private const string _rrInsert = "__pc3";
		private const string _rrUpdate = "__pc4";
		private const string _rrDelete = "__pc5";


		private RecordRightsPermissionsCacheHandler() { }
		public RecordRightsPermissionsCacheHandler(StateBag viewstate)
		{
			_viewstate = viewstate;
		}

		public void CacheResults(string viewStateKey, SecurityResultCollection results)
		{
			RecordRightsPermissionsSet rrps = new RecordRightsPermissionsSet(
				results[AceType.Record, RecordRight.List].AccessAllowed,
				results[AceType.Record, RecordRight.Select].AccessAllowed,
				results[AceType.Record, RecordRight.Insert].AccessAllowed,
				results[AceType.Record, RecordRight.Update].AccessAllowed,
				results[AceType.Record, RecordRight.Delete].AccessAllowed );

			_viewstate[viewStateKey] = rrps;
		}

		public RecordRightsPermissionsSet this[string viewStateKey]
		{
			get
			{
				return (RecordRightsPermissionsSet)_viewstate[viewStateKey];
			}
		}
	}

	[Serializable()]
	internal class RecordRightsPermissionsSet
	{
		private bool _list, _select, _insert, _update, _delete = false;

		private RecordRightsPermissionsSet() { }
		public RecordRightsPermissionsSet(bool list, bool select, bool insert, bool update, bool delete)
		{
			_list = list;
			_select = select;
			_insert = insert;
			_update = update;
			_delete = delete;
		}
		public bool List { get { return _list; } set { _list = value; } }
		public bool Select { get { return _select; } set { _select = value; } }
		public bool Insert { get { return _insert; } set { _insert = value; } }
		public bool Update { get { return _update; } set { _update = value; } }
		public bool Delete { get { return _delete; } set { _delete = value; } }
	}


	//public class GridViewImageButton : ImageButton
	//{
	//    protected override bool OnBubbleEvent(object source, EventArgs args)
	//    {
	//        return base.OnBubbleEvent( source, args );
	//    }
	//    protected override void OnCommand(CommandEventArgs e)
	//    {
	//        base.OnCommand( e );
	//    }
	//    protected override void OnClick(ImageClickEventArgs e)
	//    {
	//        base.OnClick( e );
	//    }
	//    protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
	//    {
	//        return base.LoadPostData( postDataKey, postCollection );
	//    }
	//}


	public class sGridViewSecurityAccessor : SecurityAccessor
	{
		public sGridViewSecurityAccessor(sGridView owner)
			: base( owner )
	    {
	    }
		public sGridViewSecurityAccessor(sGridView owner, AceType aceType)
			: base( owner, aceType )
	    {
	    }
		public sGridViewSecurityAccessor(sGridView owner, AceType aceType, DefaultSecurityState state)
			: base( owner, aceType, state )
	    {
	    }
		public sGridViewSecurityAccessor(sGridView owner, AceType[] aceTypes)
			: base( owner, aceTypes )
	    {
	    }
		public sGridViewSecurityAccessor(sGridView owner, AceType[] aceTypes, DefaultSecurityState state)
			: base( owner, aceTypes, state )
	    {
	    }


		public override void Apply(AceType aceType, ArrayList daclParameters, ArrayList saclParameters)
		{
			base.Apply( aceType, daclParameters, saclParameters );

			( (sGridView)this.Owner ).RecordRightsCache.
				CacheResults( string.Format( "__rrc_{0}", this.Owner.UniqueName ), this.Descriptor.SecurityResults );
		}
	}
}